package com.panfeng.xcloud.common.core.utils;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class RSAUtils {

     /**
      * 缺省的2048位密钥对,可处理245个字节(81个汉字)的数据
      */
     public static String PRIVATE_KEY = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDYXZmMYfdpEQVgFUCg8lj70EFmXrDbHNRxCBVjxdvtTUZzY33ckiuP31axZarqvuaPZOCvpjlNc0ZNamxOVBzF/qlhlNmavcvM8ZWs7xyjmm4i1apCMscWrLdEkSH3nPNBZuv2duJWkt3l/KrQvME6vfuSTFqGpNFWvWIpORkaAkKpZ2XdFJg9cQdck7CvXmsOf5UpNP/VjpBT8vZfE5PLLuI6CsUv/qywV2S+3S5NXRH3pzhq8xCZIL/lWrG06hXQ4CqUup6/xdhtMralM8IRUgjDtKBb+963QpYCuFtb5d2kaWGs6tD3gGXaryhComCFav3OgwkMoCvJUdJcPUTXAgMBAAECggEBAIe1XaPxpo8d//MeIWVR3IJFQ2AEMIWedZlX6qKj7afP+kpRsxXwEKay/NtT23pVtqNmMI+7gOGVVhkkkT4n/8woSPFNvZcTSIsJVEodyCbNrBrpTVssIjeUqXa2WUnIBcOV3JbARoLqp4ejjThTzBceJnbCsV0Wb78qFjGpAJeQf5kFhkx+BK88e5Z06C3JRbQHULmz5oLVRU48Zgcn1Jhp3ZdfKTzO9eIThq/wszcLTzRCVocx1IF66Q4UCmLE2owyR1LhZ4ZA6YioMCZPbMjAeUYPSucT8PrsNPhQZOtoF1bW5nCeAYuQuUyIQBbRNX9bbMDYj9OP7OFabuTJB2ECgYEA+jkBRITPXl6JG/9Pauz6sXFzdu6gm97y9RYHKBW9C7xc0GxIQM4OlVAkUJzIv6pOT5G+kl4T/e02VmX0ffwRp4u4Tna5n4G4Gocsqa4DcECdnvhMbqKlww/5VCv1Fvrt6Q/Rq9dmannwbiA0jcHBknHnCAaS70UDe67xj0Wqwr8CgYEA3Vx5tvYeSFLo/3Y5gcQf0f5Ruk27gx9mu0SvtLSYFjyxExqYAJo8ZwkNJYZDmCcu9J8rh8LboxYKgcFIVKMdefWb7JOHyf8wAiudZMZECt32TaEN71iDgiH9yhM2uQ05J+RINe4zj/7Gbj+FH+ijP1gNi0JOVeoj+lfJUtMQO+kCgYEAg+nFh0/U2tVPxxjDz4T7bMx4qLyIo2PYBekFANblAOjerWpIdRGskn7bhjwBgTnRaxVUuGksdPO3b7j0Oe7Hh+Ka2ZKxrSt/2Uxl+VYpreYCsqoH8VOBu+IR+ZPq86B6CCI00TkPXxbF7+i+i/UXjZLKz2pX0Bg8C9pgsr1xlpUCgYB02LWe8He3sZwwDRX5+67YSCiX8SRD6LVvsKgW+SU2x76o2ObXmpK7yLlZz2+qxzQwCD0QIrmRcrcFGyO1GY0brZwq2w1YgQ20d5VTdpzAJ7416AfVCaIRdSPkIRRHxkUfW48KeLxbDB9uXrVEzKYvb6lmkw+KpldrdB9fSu5M0QKBgQCTFBEbqMimjsf36fdEbgc4MCoqIpmnA/DCJeFiJgox1FRT4wMt9diAhLLwpdzGBfyyuZJ3eSE32eeUSE0PZyrZY9sCMCMhGNl3DtyDVmhUNrsV1+VaGBQjVObKzY3LcVy4LraOB1XVV8sZs9g2Fz6IVosIwnyla/rdBWcagaRWEg==";

    public static String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2F2ZjGH3aREFYBVAoPJY+9BBZl6w2xzUcQgVY8Xb7U1Gc2N93JIrj99WsWWq6r7mj2Tgr6Y5TXNGTWpsTlQcxf6pYZTZmr3LzPGVrO8co5puItWqQjLHFqy3RJEh95zzQWbr9nbiVpLd5fyq0LzBOr37kkxahqTRVr1iKTkZGgJCqWdl3RSYPXEHXJOwr15rDn+VKTT/1Y6QU/L2XxOTyy7iOgrFL/6ssFdkvt0uTV0R96c4avMQmSC/5VqxtOoV0OAqlLqev8XYbTK2pTPCEVIIw7SgW/vet0KWArhbW+XdpGlhrOrQ94Bl2q8oQqJghWr9zoMJDKAryVHSXD1E1wIDAQAB";

     /**
      * 字符集
      */
     public static String CHARSET = "utf-8";

     /**
      * 签名算法
      */
     public static final String SIGNATURE_INSTANCE = "SHA1WithRSA";

    /**
     * 生成密钥对
     * @param keyLength
     * @return
     * @throws Exception
     */
    public static KeyPair getKeyPair(int keyLength) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(keyLength);
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 公钥字符串转PublicKey实例
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(String publicKey) throws Exception {
         byte[] publicKeyBytes = Base64.getDecoder().decode(publicKey.getBytes());
         X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
         return keyFactory.generatePublic(keySpec);
     }

    /**
     * 私钥字符串转PrivateKey实例
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String privateKey) throws Exception {
         byte[] privateKeyBytes = Base64.getDecoder().decode(privateKey.getBytes());
         PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
         return keyFactory.generatePrivate(keySpec);
     }

    /**
     * 公钥加密
     * @param content
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] content, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(content);
    }

    public static byte[] encryptByPublicKey(byte[] content) throws Exception {
        return encryptByPublicKey(content, getPublicKey(PUBLIC_KEY));
    }

    public static String encryptByPublicKey(String content, String publicKey) throws Exception {
       return new String(Base64.getEncoder().encode(encryptByPublicKey(content.getBytes(CHARSET), getPublicKey(publicKey))));

    }

    public static String encryptByPublicKey(String content) throws Exception {
        return new String(Base64.getEncoder().encode(encryptByPublicKey(content.getBytes(CHARSET))));
    }

    /**
     * 私钥解密
     * @param content
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] content, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(content);
    }

    public static byte[] decryptByPrivateKey(byte[] content) throws Exception {
        return decryptByPrivateKey(content, getPrivateKey(PRIVATE_KEY));
    }

    public static String decryptByPrivateKey(String content, String privateKey) throws Exception {
        return new String(decryptByPrivateKey(Base64.getDecoder().decode(content), getPrivateKey(privateKey)), CHARSET);

    }

    public static String decryptByPrivateKey(String content) throws Exception {
        return new String(decryptByPrivateKey(Base64.getDecoder().decode(content)), CHARSET);
    }

    /**
     * 私钥加密
     * @param content
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] content, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        return cipher.doFinal(content);
    }

    public static byte[] encryptByPrivateKey(byte[] content) throws Exception {
        return encryptByPrivateKey(content, getPrivateKey(PRIVATE_KEY));
    }

    public static String encryptByPrivateKey(String content, String privateKey) throws Exception {
        return new String(encryptByPrivateKey(content.getBytes(CHARSET), getPrivateKey(privateKey)), CHARSET);
    }

    public static String encryptByPrivateKey(String content) throws Exception {
        return new String(encryptByPrivateKey(content.getBytes(CHARSET)), CHARSET);
    }

    /**
     * 公钥解密
     * @param content
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static byte[] decrypByPublicKey(byte[] content, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        return cipher.doFinal(content);
    }

    public static byte[] decrypByPublicKey(byte[] content) throws Exception {
        return decrypByPublicKey(content, getPublicKey(PUBLIC_KEY));
    }

    public static void main(String[] args) throws Exception {
        String signString = "VAJlc4iJQnGTgov9y+2dQ4Rcl7rtXhH0mAtzu9aj4P77FVz8JGFBsiYI4Z5A0SitNPTnQNX5lb2NGsfg8o2QgGKx/SAlUAmFqKbCqUgJ2e0VjtWLi2/7M/oZFdFZ+1jN7UIKV/dGFWKBQO9rfSlQocMdr0SWwRQDi2GiqWptiS4ao3IlsuhsoTWq/R1ZclT+kkqTA7uYHxlq718Y1qRal0ni1LqLCRgkHLixcSI7IvR1yYn74PAuxEW6rD5XmuW82vOxU1M6KDBZSq+zLw+h10MzsxGymzg2bfSsClTOqWVpNshYjJPLg/6s/7Qa5gKfOsvK5nML4rCgP3JEVvyeAw==";
        System.out.println("验证签名结果 : " + verify("sys/menu/queryUserSysMenuTree",signString));
    }

    public static String decrypByPublicKey(String content, String publicKey) throws Exception {
        return new String(decrypByPublicKey(Base64.getDecoder().decode(content), getPublicKey(publicKey)), CHARSET);

    }

    public static String decrypByPublicKey(String content) throws Exception {
        return new String(decrypByPublicKey(Base64.getDecoder().decode(content)), CHARSET);
    }

    /**
     * 签名
     * @param content
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static byte[] sign(byte[] content, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance(SIGNATURE_INSTANCE);
        signature.initSign(privateKey);
        signature.update(content);
        return signature.sign();
    }

    public static byte[] sign(byte[] content) throws Exception {
        return sign(content, getPrivateKey(PRIVATE_KEY));
    }

    public static String sign(String content, String privateKey) throws Exception {
        return new String(Base64.getEncoder().encode(sign(content.getBytes(CHARSET), getPrivateKey(privateKey))), CHARSET);
    }

    public static String sign(String content) throws Exception {
        return new String(Base64.getEncoder().encode(sign(content.getBytes(CHARSET))), CHARSET);
    }

    /**
     * 验签
     * @param content
     * @param sign
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static boolean verify(byte[] content, byte[] sign,  PublicKey publicKey) throws Exception {
        Signature signature = Signature.getInstance(SIGNATURE_INSTANCE);
        signature.initVerify(publicKey);
        signature.update(content);
        return signature.verify(sign);
    }

    public static boolean verify(byte[] content, byte[] sign) throws Exception {
        return verify(content, sign, getPublicKey(PUBLIC_KEY));
    }

    public static boolean verify(String content, String sign, String publicKey) throws Exception {
        return verify(content.getBytes(CHARSET), Base64.getDecoder().decode(sign), getPublicKey(publicKey));
    }

    public static boolean verify(String content, String sign) throws Exception {
        return verify(content.getBytes(CHARSET), Base64.getDecoder().decode(sign), getPublicKey(PUBLIC_KEY));
    }
}
